
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.ProBuilder.MeshOperations;


public  class MGameUser:GameUser
{
    private List<Moment> m_Moments = new List<Moment>();
    public List<Moment> moments { get => m_Moments; set => m_Moments = value; }
    private string m_Status;
    public string status => m_Status;
    public int belikeNum => this.belikes.Count;
    public int followersNum => followers.Count;
    int m_GuestNum;
    public int guestNum => m_GuestNum;

    public int myApplyNum
    {
        get
        {
            int count = 0;
            for(int i = 0; i < applies.Count; i++)
            {
                if (applies[i].sourceUserId == this.id)
                    count++;
            }
            return count;
        }
    }

    private UserInfo m_UserInfo;
    public UserInfo userInfo => m_UserInfo;
    
    private List<Apply> m_Applys = new List<Apply>();
    public List<Apply> applies => m_Applys;
    List<Chat> m_Chats = new List<Chat>();
    public List<Chat> chats => m_Chats;
    List<long> m_Friends = new List<long>();
    public List<long> friends => m_Friends;

    List<long> m_likes = new List<long>();
    public List<long> likes
    {
        get => m_likes;
        set => m_likes = value;
    }
    List<long> m_belikes = new List<long>();
    public List<long> belikes
    {
        get => m_belikes;
        set => m_belikes = value;
    }
    List<Visit> m_visitors = new List<Visit>();
    public List<Visit> visitors
    {
        get => m_visitors;
        set => m_visitors = value;
    }
    List<Visit> m_myVisits = new List<Visit>();
    public List<Visit> myVisits
    {
        get => m_myVisits;
        set => m_myVisits = value;
    }
    int m_freeApplyCount;
    public int freeApplyCount => m_freeApplyCount;
    Requirement m_Requirement;
    public Requirement requirement => m_Requirement;

    public List<long> myFollows;
    public List<long> followers;
    protected override void _Init(LocalUserData localUserData)
    {
        MLocalUserData mLocalUserData = localUserData as MLocalUserData;

        if (mLocalUserData == null)
        {
            GameDebug.LogError($"dguLocalUserData == null  {localUserData.GetType().Name}");
            return;
        }
        
        this.m_Status = mLocalUserData.status;
        
        if (mLocalUserData.moments != null)
        {
            this.m_Moments = new List<Moment>(mLocalUserData.moments);
        }
        this.m_UserInfo = mLocalUserData.userInfo;

        if (this.m_UserInfo == null)
        {
            m_UserInfo = new UserInfo();
            //m_UserInfo.TestCandidate(1);
        }

        GameDebug.Log($"cur Role Id:{mLocalUserData.status} userInfo:{this.userInfo} mLocalUserData.userInfo:{mLocalUserData.userInfo}");
        
        if (mLocalUserData.applies != null)
        {
            this.m_Applys = new List<Apply>(mLocalUserData.applies);
        }
        if (mLocalUserData.chats != null)
        {
            this.m_Chats = new List<Chat>(mLocalUserData.chats);
        }
    }

    public override LocalUserData GetLocalUserData()
    {
        return  MLocalUserData.User2Data(this);
    }

    public void InitWithServerData(User user,bool needUpdateIcon, bool needUpdateTex1, bool needUpdateTex2,
        bool needUpdateTex3, bool needUpdateTex4, bool needUpdateTex5, bool needUpdateTex6)
    {
        GameDebug.Log($"InitWithServerData:{user.id} diamond:{user.diamond} userInfo:{user.userInfo}");

        this.m_Id = user.id;
        this.m_Name = user.name;
        this.m_Coin = user.coin;
        this.m_Diamond = user.diamond;
        this.m_Level = user.level;
        this.m_freeApplyCount = user.freeApplyCount;

        this.m_MemberTimeEndDate = user.memberTimeEndDate;
        //this.m_LoginDays = user.loginDays;
        this.m_Status = user.userInfo.status;
        if (user.moments != null)
        {
            this.m_Moments = new List<Moment>(user.moments);
        }

        if (!needUpdateIcon) user.userInfo.icon = m_UserInfo.icon;
        if (!needUpdateTex1) user.userInfo.tex1 = m_UserInfo.tex1;
        if (!needUpdateTex2) user.userInfo.tex2 = m_UserInfo.tex2;
        if (!needUpdateTex3) user.userInfo.tex3 = m_UserInfo.tex3;
        if (!needUpdateTex4) user.userInfo.tex4 = m_UserInfo.tex4;
        if (!needUpdateTex5) user.userInfo.tex5 = m_UserInfo.tex5;
        if (!needUpdateTex6) user.userInfo.tex6 = m_UserInfo.tex6;

        this.m_UserInfo = user.userInfo;
        if (this.m_UserInfo == null)
        {
            m_UserInfo = new UserInfo();
            m_UserInfo.TestCandidate(1);
        }
        if(m_UserInfo.userId != id)
        {
            GameDebug.LogError($"m_UserInfo.userId :{m_UserInfo.userId} != id:{id}");
            userInfo.userId = id;
        }
        if (user.applies != null)
        {
            this.m_Applys = new List<Apply>(user.applies);
        }
        if (user.chats != null)
        {
            this.m_Chats = new List<Chat>(user.chats);
        }
        if (user.visitors != null)
            m_visitors = new List<Visit>(user.visitors);
        if (user.myVisits != null)
            m_myVisits = new List<Visit>(user.myVisits);

        if (user.likes != null)
            m_likes = new List<long>(user.likes);
        if (user.belikes != null)
            m_belikes = new List<long>(user.belikes);

        if (user.followers != null)
            followers = new List<long>(user.followers);
        if (user.myFollows != null)
            myFollows = new List<long>(user.myFollows);

        m_Requirement = user.requirement;

        GameDebug.Log($"user applies count:{user.applies?.Count}  chats count:{user.chats.Count}  m_Requirement minAge:{m_Requirement.minAge}  myVisits:{myVisits.Count}  visitors:{visitors}");
        
        UpdateLocalData();
    }

    //public bool IsSkinUnlock(int skinId)
    //{
    //    bool unlock = this.moments.Contains(skinId) || skinId == ConstantData.defaultSkin;
    //    //GameDebug.LogError($"skins:{skins.GetListStr()} to check skinId:{skinId}  unlock:{unlock}");
    //    return unlock;
    //}


    public bool AddSkin(int id)
    {
        return true;
    }

    public void UpdateApply(Apply apply)
    {
        for (int i = 0; i < applies.Count; i++)
        {
            if (applies[i].targetUserId == apply.targetUserId)
                applies[i] = apply;
        }
        UpdateLocalData();
    }

    public Apply AddApply(long sourceUserId,long targetUserId, int result, string msg,string rejectMsg,long time)
    {
        var apply = this.applies.Find(e => e.targetUserId == targetUserId);
        
        if (apply != null)
        {
            apply.result = result;
            UpdateLocalData();
            return apply;
        }
        else
        {
            var newApply = new Apply() { sourceUserId = sourceUserId, targetUserId = targetUserId, result = result, msg = msg, rejectMsg = rejectMsg, applyTime = time };
            this.applies.Add(newApply);
            UpdateLocalData();
            return newApply;
        }
    }
    public void AddApply(Apply apply)
    {
        bool free = freeApplyCount > 0;
        if (!free)
        {
            if (diamond >= AppConstantData.applyPrice)
                AddDiamond(-AppConstantData.applyPrice, false);
            else
                return;
        }
        else
        {
            m_freeApplyCount--;
        }

        if (apply == null)
            return;

        bool exist = false;
        for (int i = 0; i < this.applies.Count; i++)
        {
            if (applies[i].targetUserId == apply.targetUserId)
            {
                applies[i] = apply;
                exist = true;
            }
        }
        if(!exist)
        {
            this.applies.Add(apply);
        }
        UpdateLocalData();
    }

    public Chat AddDialogue(long fromId,long toId,string  content,long time)
    {
        bool me = fromId == this.id;

        Chat chat = this.chats.Find(e => e.AreUser(fromId, toId));
        
        if (chat != null)
        {
            var diaogue = new Dialogue() {message = content, time = time };
            chat.dialogues = chat.dialogues.ArrayAdd<Dialogue>(diaogue);
            //GameDebug.Log($"data add dialogue:{fromId} {toId} :{chat.dialogues.Length}");
            if(!me)
                chat.newMsgCount++;
            UpdateLocalData();
            return chat;
        }
        else
        {
            var diaogue = new Dialogue() { message = content, time = time };
            chat = new Chat()
            {
                userId1 = fromId,
                userId2 = toId,
                dialogues = new[]
                {
                    diaogue
                },
                newMsgCount = me ? 0 : 1
            };
            //GameDebug.Log($"data new chat dialogue:{fromId} {toId}");
            this.chats.Add(chat);
            UpdateLocalData();
            return chat;
        }
    }
    public void AddFriend(long friend)
    {
        if (m_Friends == null)
            m_Friends = new List<long>();

        if (!this.m_Friends.Contains(friend))
            m_Friends.Add(friend);
    }

    public void UpdateChat(Chat chat)
    {
        for(int i=0;i< chats.Count; i++)
        {
            if (chats[i].userId1 == chat.userId1)
                chats[i] = chat;
        }
        UpdateLocalData();
    }
    public Chat GetChat(long targetUserId)
    {
        for (int i = 0; i < chats.Count; i++)
        {
            if (chats[i].userId1 == targetUserId)
                return chats[i];
        }
        var chat = new Chat()
        {
            userId1 = targetUserId,
            dialogues = new Dialogue[0],
            newMsgCount = 0
        };
        this.chats.Add(chat);
        UpdateLocalData();
        return chat;
    }
    /*public void UpdateCurSkinId(int skinId)
    {
        if (m_CurRoleId != skinId)
        {
            this.m_CurRoleId = skinId;
            UpdateLocalData();
        }
    }*/

    public void UpdateHeight(float targetValue)
    {
        var fived = this.userInfo;
        fived.height = targetValue;
        UpdateUserInfo(fived);
    }
    public void UpdateWeight(float targetValue)
    {
        var fived = this.userInfo;
        fived.weight = targetValue;
        UpdateUserInfo(fived);
    }
    public void UpdateIncome(int targetValue)
    {
        var fived = this.userInfo;
        fived.income = targetValue;
        UpdateUserInfo(fived);
    } 
    public void UpdateEducation(int targetValue)
    {
        if (targetValue > UIPropertyShow.maxEducation) return;
        
        var fived = this.userInfo;
        fived.eduation = targetValue;
        UpdateUserInfo(fived);
    }

    void UpdateUserInfo(UserInfo fiveD)
    {
        m_UserInfo = fiveD;
        UpdateLocalData();
    }
    
    public int UpgradeSpeedLevel(bool ad = false)
    {
        int nextLevel = this.belikeNum + 1;
        int price = MLocalUserData.GetUpgradePrice(nextLevel);
        
        if (this.coin >= price || ad)
        {
            if(!ad)
                this.ReduceCoin(price,false);
            UpdateLocalData();
            return nextLevel;
        }

        return belikeNum;
    }
    public int UpgradeEnduranceLevel(bool ad = false)
    {
        int nextLevel = this.followersNum + 1;
        int price = MLocalUserData.GetUpgradePrice(nextLevel);
        
        if (this.coin >= price || ad)
        {
            //m_FollowNum++;
            if(!ad)
                this.ReduceCoin(price,false);
            UpdateLocalData();
            return nextLevel;
        }

        return followersNum;
    }

    public int UpgradeArmLengthLevel(bool ad = false)
    {
        int nextLevel = this.guestNum + 1;
        int price = MLocalUserData.GetUpgradePrice(nextLevel);

        if (this.coin >= price || ad)
        {
            m_GuestNum++;
            if(!ad)
                this.ReduceCoin(price, false);
            UpdateLocalData();
            return nextLevel;
        }

        return guestNum;
    }
    public void UpdateRequire(Requirement requirement)
    {
        m_Requirement = requirement;
    }

    public void AddMyVisit(Visit visit)
    {
        this.myVisits.Add(visit);
    }

    public void AddVisitor(Visit visit)
    {
        this.visitors.Add(visit);
    }

    public void AddLike(long toUserId)
    {
        if (this.m_likes == null)
            m_likes = new List<long>();

        if (!likes.Contains(toUserId))
            this.likes.Add(toUserId);
    }

    public void AddBeLike(long likeFromUserId)
    {
        if (this.m_belikes == null)
            m_belikes = new List<long>();

        if (!m_belikes.Contains(likeFromUserId))
            m_belikes.Add(likeFromUserId);
    }
    public void AddMoment(Moment moment)
    {
        if (this.m_Moments == null)
            m_Moments = new List<Moment>();

        m_Moments.Add(moment);
    }
    public void AddMyFollow(long targetUser)
    {
        if (this.myFollows == null)
            myFollows = new List<long>();

        if (!this.myFollows.Contains(targetUser))
            myFollows.Add(targetUser);
    }
    public void AddFollower(long targetUser)
    {
        if (this.followers == null)
            followers = new List<long>();

        if (!this.followers.Contains(targetUser))
            followers.Add(targetUser);
    }
    public void RemoveMyFollow(long targetUser)
    {
        if (this.myFollows != null)
            myFollows.Remove(targetUser);
    }
    public void RemoveFollower(long targetUser)
    {
        if (this.followers != null)
            followers.Remove(targetUser);
    }
}